//登录、注册模块的小仓库
import { login, refreshToken, register } from '@/api';
import options from '@/api/option-api';
const EMPTY_SESSION = () => ({
    token: null,
    refreshToken: '',
    tokenHead: '',
    expiresIn: 0,
    authorities: [],
    // 以下为客户端自定义信息
    rememberMe: false,
    language: ''
})

const EMPTY_USER = () => ({
    id: null,
    username: null,
    nickname: ''
})

let state = {
    session: options.hasSession() ? Object.assign(EMPTY_SESSION(), options.getSession()) : EMPTY_SESSION(),
    user: EMPTY_USER(),
};
let mutations = {
    /**
     * 登陆成功，设置登录状态
     *
     * @param state
     * @param session 客户端的Session
     *
     * 服务端不存储状态，登陆成功后用户状态信息通过JWT返回浏览器，存储在客户端Session中，其结构为：
     * { username, scope, expires, access_token, refresh_token, token_type, jti }
     * 另，根据用户在客户端登陆时的选项，以下内容也被添加到客户端Session中：
     * { rememberMe, location }
     */
    setupSession(state, session) {
        // 服务端传来的session过期时间是相对时间（因为服务端、客户端的时间可能不一致），存储到本地时，转为绝对时间戳
        // 注意服务端返回的时间单位是秒，客户端的时间戳是毫秒
        session.expiresIn = new Date().getTime() + (session.expiresIn * 1000)
        Object.assign(state.session, session)
        options.setSession(session)
    },

    /**
     * 退出登陆状态
     * 清理vuex中的所有状态（Session、Account），以及本地存储中的Session
     */
    clearSession(state) {
        state.session = EMPTY_SESSION()
        state.user = EMPTY_USER()
        options.removeSession()
    },

    /**
     * 更新用户账号资料
     */
    updateUser(state, user) {
        //console.log(user)
        if (user != null) {
            state.user.id = user.id
            state.user.username = user.username
            state.user.nickname = user.realName
            //console.log(user)
            if (user.authorities.length > 0) {
                for (var i = 0; i < user.authorities.length; i++) {
                    if (undefined === user.authorities[i].authority) {
                        // springcloud设值
                        state.session.authorities.push(user.authorities[i])
                    } else {
                        // springboot设值
                        state.session.authorities.push(user.authorities[i].authority)
                    }

                    
                }
            }
        }
        // 这个方法会把后台传过来的数据覆盖掉
        //Object.assign(state.user, user)
    },

};
let actions = {
    //用户注册
    async registerUser({ commit, state, dispatch }, obj) {
        let result = await register(obj);
        // 注册成功
        if (result.code == 200) {
            return '200';
        } else {
            //注册失败
            return Promise.reject(new Error(result.msg));
        }
    },
    //用户登录
    async userLogin({ commit, state, dispatch }, obj) {
        let result = await login(obj.username, obj.password);
        //登录成功
        if (result.error == null && result.code == 200) {
            result.data.rememberMe = obj.rememberMe;
            commit('setupSession', result.data);
            return '200';
        } else {
            //登录失败
            return Promise.reject(new Error(result.msg));
        }
    },
    //退出登录的业务
    async logout({ commit, state, dispatch }) {

    },
    /**
     * 根据过期时间刷新OAuth令牌的触发器
     */
    refreshSessionTrigger({ dispatch, commit, state }) {
        // Session是具有有效期的，设置更新令牌的触发器
        let timeout = state.session.expiresIn - new Date().getTime()
        if (timeout > 0) {
            console.log(`Session将在：${timeout}毫秒后过期，届时会重刷新令牌`)
            setTimeout(() => {
                dispatch('refreshSession', { commit, state }).then(() => {
                    dispatch('refreshSessionTrigger', { commit, state })
                })
            }, timeout)
        }
    },
    /**
     * 向服务端请求新的访问令牌
     */
    async refreshSession({ commit, state }) {
        try {
            let { data } = await refreshToken(state.session.refreshToken)
            commit('setupSession', data)
        } catch (e) {
            // 刷新失败，就清理掉当前的用户
            commit('clearSession')
        }
    }


};
let getters = {
    /**
     * 检查授权是否有效
     * 生效要求：持有JWT令牌，且并未超出令牌期限
     */
    isAuthorized: state => !!state.session.token && (state.session.expiresIn > new Date().getTime()),

    /**
     * 是否为管理员
     */
    isAdministrator: (state, getters) => getters.isAuthorized && state.session.authorities.includes('ROLE_ADMIN')

};
//对外暴露
export default {
    state,
    mutations,
    actions,
    getters
}